package phoenixAAD.WifiFlashDrive;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;

public class WiFiFlashDriveActivity extends Activity {
	private static final String CLIENT_COLOR = "#6495ED";
	private static final String SERVER_COLOR = "#71BC78";
	private static final String EXCEPTION_COLOR = "#FA8072";
	private static final String FTP_HEADER = "ftp://";
	private TextView log;
	private ScrollView scroll;

	private WifiManager mWifiManager;

	private int port = 50000; // must be 1024 < x < 65535,

	private Button btnStart, btnStop;
	private ProgressBar progressBar;
	
	
	final String packageName = "phoenixAAD.WifiFlashDrive";
	private static final int FIRST_TIME_SETTINGS = 1;
	private static final int SETTINGS = 2;
	
	private String username;
	private String password;
	public static String IP_ADDRESS;
	public static int PORT_NUMBER;
	
	private TextView progressBarTitle;
	private TextView addressView;
	private CheckBox compatibility;
	
	
	private static final String PREF_COMPATIBLE = "compatible";
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		if (checkPreferences()) {
			// set settings
			Log.d("debug","default settings have been detected...starting preference activity");
			Intent intent = new Intent(WiFiFlashDriveActivity.this,
					SettingsActivity.class);
			startActivityForResult(intent, FIRST_TIME_SETTINGS);
			
		}
		
		//Log.d("debug", "custom settings detected. Starting main actvity");
		SharedPreferences preferences = getSharedPreferences(packageName+ "_preferences", MODE_PRIVATE);
		username =preferences.getString("editUsername", "empty");
		password = preferences.getString("editPassword", "empty");
		Log.d("debug","username: " + username);
		Log.d("debug", "pw: " + password);
		
		setContentView(R.layout.main);
		
		compatibility = (CheckBox) findViewById(R.id.compatibility);
		compatibility.setChecked(preferences.getBoolean(PREF_COMPATIBLE, false));
		compatibility.setOnCheckedChangeListener(new  OnCheckedChangeListener(){
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				AlertDialog.Builder alertDialog = new AlertDialog.Builder(WiFiFlashDriveActivity.this);
				alertDialog.setTitle(getString(R.string.caution));
				alertDialog.setMessage(getString(R.string.caution_encoding));
				alertDialog.setNegativeButton(getString(android.R.string.ok), null);
				alertDialog.show();
				SharedPreferences preferences = getSharedPreferences(packageName+ "_preferences", MODE_PRIVATE);
				Editor editor = preferences.edit();
				editor.putBoolean(PREF_COMPATIBLE, isChecked);
				editor.commit();
			}
		});
		log = (TextView) findViewById(R.id.log);
		log.setText("", TextView.BufferType.SPANNABLE);
		scroll = (ScrollView) findViewById(R.id.scroll);

		btnStart = (Button) this.findViewById(R.id.start);
		btnStart.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) // SD card not present
				{
					AlertDialog.Builder alertDialog = new AlertDialog.Builder(WiFiFlashDriveActivity.this);
					alertDialog.setTitle(getString(R.string.warn_nostorage_title));
					alertDialog.setMessage(getString(R.string.warn_nostorage));
					alertDialog.setNegativeButton(getString(android.R.string.ok), null);
					alertDialog.show();
				}
				else if(!username.equals("empty")&&!password.equals("empty")){
					PORT_NUMBER=port;
					Intent serverIntent = new Intent(WiFiFlashDriveActivity.this,
							FTP.class);
					Messenger messenger = new Messenger(new NetworkHandler());
					serverIntent.putExtra(FTP.MESSENGER, messenger);
					serverIntent.putExtra(FTP.PORT, port);
					serverIntent.putExtra(FTP.INTENT_ROOT, Environment.getExternalStorageDirectory().getPath());
					serverIntent.putExtra("username", username);
					serverIntent.putExtra("password", password);
					serverIntent.putExtra(FTP.COMPATIBILITY, getSharedPreferences(packageName+ "_preferences", MODE_PRIVATE).getBoolean(PREF_COMPATIBLE, false));
					startService(serverIntent);	 
					
				}else{
					AlertDialog.Builder alertDialog = new AlertDialog.Builder(WiFiFlashDriveActivity.this);
					alertDialog.setTitle(getString(R.string.warning));
					alertDialog.setMessage(getString(R.string.warn_nosetting));
					alertDialog.setNegativeButton(getString(android.R.string.ok), null);
					alertDialog.show();
				}
			} 

			
		});
		btnStop = (Button) this.findViewById(R.id.stop);
		btnStop.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if(FTP.isTransferring())
				{
					AlertDialog.Builder alertDialog = new AlertDialog.Builder(WiFiFlashDriveActivity.this);
					alertDialog.setTitle(getString(R.string.caution));
					alertDialog.setMessage(getString(R.string.caution_forcestop));
					alertDialog.setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener(){
						public void onClick(DialogInterface dialog, int which) {
							stopService(new Intent(WiFiFlashDriveActivity.this, FTP.class));
						}
					});
					alertDialog.setNegativeButton(getString(android.R.string.no), null);
					alertDialog.show();
					
				}
				else
					stopService(new Intent(WiFiFlashDriveActivity.this, FTP.class));
			}
		});

		if (FTP.isServerRunning()) {
			// update messenger so this activity will receive the logs
			FTP.setMessenger(new Messenger(new NetworkHandler()));
			writeLog(getString(R.string.status_online)); 
		} else
			writeLog(getString(R.string.status_offline));

		// show IP address

		mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		String ipAddress = "";

		try {
			if (mWifiManager.isWifiEnabled()) {
				ipAddress = getWifiIpAddress();
			} else {
				ipAddress = get3GIpAddress();
			}
		} catch (RuntimeException e) // running on emulator
		{
			// ipAddress = get3GIpAddress();
		}
		IP_ADDRESS=ipAddress;
		writeLog(ipAddress + ":" + port);
		
		addressView = (TextView) this.findViewById(R.id.address);
		addressView.setText(FTP_HEADER + ipAddress + ":" + port);
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
	}

	private boolean checkPreferences() {
		SharedPreferences preferences = getSharedPreferences(packageName+ "_preferences", MODE_PRIVATE);
		if (preferences.contains("defaultSettings")) {
			boolean defaultSettings = preferences.getBoolean("defaultSettings",true);
			return defaultSettings;
		} else {
			Editor editor = preferences.edit();
			editor.putBoolean("defaultSettings", true);
			editor.commit();
			return true;
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == FIRST_TIME_SETTINGS || requestCode == SETTINGS) {
			if (resultCode == 1) {
				Bundle b = data.getExtras();
				String username = b.getString("username");
				String pw = b.getString("password");
				SharedPreferences preferences = getSharedPreferences(
						packageName + "_preferences", MODE_PRIVATE);
				Editor editor = preferences.edit();

				editor.putString("editUsername", username);
				editor.putString("editPassword", pw);
				editor.putBoolean("defaultSettings", false);
				editor.commit();
			
				this.username = username;
				this.password = pw;
			}
		}

	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()){
		case R.id.settings:
		{
			Intent i = new Intent(this,SettingsActivity.class);
			Bundle b = new Bundle();
			b.putBoolean("defaultStart", false);
			i.putExtras(b);
			startActivityForResult(i, SETTINGS);
			break;
		}
		case R.id.help:
		{
			this.startActivity(new Intent(this, HelpActivity.class));
		}
		}		
		return true;
	}

	// only works if wifi connection
	public String getWifiIpAddress() {
		WifiInfo mWifiInfo = mWifiManager.getConnectionInfo();
		int ipInt = mWifiInfo.getIpAddress();
		String ipString = ((ipInt >> 0) & 0xFF) + "." + ((ipInt >> 8) & 0xFF)
				+ "." + ((ipInt >> 16) & 0xFF) + "." + ((ipInt >> 24) & 0xFF);
		return ipString;
	}

	public String get3GIpAddress() {
		String ipAddress = null;
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface
					.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf
						.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress()) {
						ipAddress = inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (SocketException ex) {
		}
		return ipAddress;
	}

	/**
	 * Writes the specified string to the log
	 */
	private void writeLog(String string) {
		Log.d("log", string);
		log.append(string + "\n");
		scroll.post(new Runnable() {

			public void run() {
				scroll.smoothScrollTo(0, log.getBottom());
			}
		});
	}
	
	/**
	 * Writes the specified string to the log
	 */
	private void writeLog(String string, String color) {
		Log.d("log", string);
		log.append(Html.fromHtml("<font color='" + color + "'>" + string.replaceAll("\n", "<br>") + "</font>"));
		log.append("\n");
		scroll.post(new Runnable() {

			public void run() {
				scroll.smoothScrollTo(0, log.getBottom());
			}
		});
	}

	/**
	 * A handler class to receive messages from the network components
	 */
	private class NetworkHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case FTP.LOG:
				writeLog((String) msg.obj);
				break;
			case FTP.CLIENT_LOG:
				writeLog((String) msg.obj, CLIENT_COLOR);
				break;
			case FTP.SERVER_LOG:
				writeLog((String) msg.obj, SERVER_COLOR);
				break;
			case FTP.SERVER_INIT_ERROR:
				writeLog(getString(R.string.error_server_not_created));
				break;
			case FTP.SERVER_EXCEPTION:
				writeLog(((IOException) msg.obj).toString(), EXCEPTION_COLOR);
				((IOException) msg.obj).printStackTrace();
				break;
			case FTP.PROGRESS_BAR:
				int status = (Integer)msg.obj;
				if(progressBar==null || progressBarTitle==null){
					progressBar = (ProgressBar)findViewById(R.id.progressBar);
					progressBarTitle = (TextView) findViewById(R.id.progressBarTitle);
				}
				if(status>=0&&status<100){					
					if(ProgressBar.INVISIBLE == progressBar.getVisibility()){
						progressBar.setVisibility(ProgressBar.VISIBLE);
						progressBarTitle.setVisibility(TextView.VISIBLE);
					}
					progressBar.setProgress(status);
					progressBarTitle.setText(getString(R.string.status_send)+status+"%");
				}
				else if(status <= 100){
					progressBar.setVisibility(ProgressBar.INVISIBLE);
					progressBarTitle.setVisibility(TextView.INVISIBLE);
				}
				else if(status<0){
					progressBar.setVisibility(ProgressBar.INVISIBLE);
				}
				break;
			case FTP.INDETERMINATE_PROGRESS: // for receiving
				boolean isOn = (Boolean) msg.obj;
				if(progressBar==null || progressBarTitle==null){
					progressBar = (ProgressBar)findViewById(R.id.progressBar);
					progressBarTitle = (TextView) findViewById(R.id.progressBarTitle);
				}
				if(isOn)
				{
					progressBar.setVisibility(ProgressBar.VISIBLE);
					progressBarTitle.setVisibility(TextView.VISIBLE);
					progressBarTitle.setText(getString(R.string.status_receive));
					progressBar.setIndeterminate(true);
				}
				else
				{
					progressBar.setIndeterminate(false);
					progressBar.setVisibility(ProgressBar.INVISIBLE);
					progressBarTitle.setVisibility(TextView.INVISIBLE);
				}
				break;
				
			default:
				throw new RuntimeException(
						"Handler: unknown message was passed");
			}
		}
	}
}